#!/bin/sh

# MERCKU_FACTORY_MODE
MERCKU_FACTORY_MODE=$(mercku_mtd get_factory_mode)
# null or 1: factory mode
# 0: not factory mode

# MERCKU_WORK_ROLE
MERCKU_WORK_ROLE=$(uci get system.global.work_role)
# 0: undefined
# 1: master
# 2: slave

# MERCKU_WORK_MODE
MERCKU_WORK_MODE=$(uci get system.global.work_mode)
# 0: undefined
# 1: gateway
# 2: bridge

# MERCKU_IS_INIT
MERCKU_IS_INIT=$(uci get system.global.is_init)
# 1: not configured yet
# 0: configured

# MESH_2G_ENABLE
MESH_2G_ENABLE=$(uci get system.mesh.mesh_2g_enable)
# 1: enabled
# 0: disabled

MERCKU_NETWORK_LOCK_FILE="/var/run/mercku/mercku_network.lock"

# MAIN_5G
MERCKU_MAIN_5G_ENABLED=$(uci get wireless.main_5g.enabled)
# 1: enabled
# 0: disabled

# TxPower
MERCKU_WIFI_TXPOWER=$(uci get wireless.main_5g.txpower)

# Channel
MERCKU_CHANNEL_CONFIG=$(uci get wireless.main_2g.channel)

# MERCKU_STATUS_LED_NERWORK_STATE
MERCKU_STATUS_LED_NERWORK_STATE=$(uci get system.status_led.event_id)

MERCKU_NODE_STATE_NORMAL=0
MERCKU_NODE_STATE_UPGRADING=1
MERCKU_NODE_STATE_UPGRADED_FAILED=2
MERCKU_NODE_STATE_DOWNLOADING_FW=3
MERCKU_NODE_STATE_DOWNLOAD_FW_FAILED=4
MERCKU_NODE_STATE_INSTALLING_FW=5
MERCKU_NODE_STATE_INSTALL_FW_FAILED=6
MERCKU_NODE_STATE_REBOOTING=7
MERCKU_NODE_STATE_RESETING=8
MERCKU_NODE_STATE_OFFLINE=9

E_FW_DOWNLOAD_FAILED=600107
E_FW_UGREADE_FAILED=600108
E_FW_UGREADE_SUCCESSFUL=600109

MERCKU_UPGREADING=0
MERCKU_UPGREADE_FAILED=1
MERCKU_UPGREADE_SUCCESSFUL=2
MERCKU_UPGRADE_INSTALLATION=3
MERCKU_UPGREADE_DOWNLOADING=4
MERCKU_UPGREADE_DOWNLOAD_FAILED=5
MERCKU_UPGREADE_DOWNLOAD_SYCCESSFUL=6

# router mode
MERCKU_MODE_GATEWAY=1
MERCKU_MODE_BRIDGE=2
MERCKU_MODE_WIRELESS_BRIDGE=5

# router role
MERCKU_ROLE_MASTER=1
MERCKU_ROLE_SLAVE=2
MERCKU_ROLE_UNDEFINED=0

MERCKU_FACTORY_TEST_FILE='/var/run/mercku_factory_test'
MERCKU_MESH_NODE_STATE_FILE='/tmp/mesh_node_state'

[ -e $MERCKU_MESH_NODE_STATE_FILE ] && MERCKU_MESH_NODE_STATE=$(cat $MERCKU_MESH_NODE_STATE_FILE) || MERCKU_MESH_NODE_STATE=$MERCKU_NODE_STATE_NORMAL

is_master() {
    [[ "$MERCKU_WORK_ROLE" -eq $MERCKU_ROLE_MASTER ]]
}

is_slave() {
    [[ "$MERCKU_WORK_ROLE" -eq $MERCKU_ROLE_SLAVE ]]
}

is_role_undefined() {
    [[ "$MERCKU_WORK_ROLE" -eq $MERCKU_ROLE_UNDEFINED ]]
}

is_gw() {
    [[ "$MERCKU_WORK_MODE" -eq $MERCKU_MODE_GATEWAY ]]
}

is_br() {
    [[ "$MERCKU_WORK_MODE" -eq $MERCKU_MODE_BRIDGE ]]
}

is_wireless_br() {
    [[ "$MERCKU_WORK_MODE" -eq $MERCKU_MODE_WIRELESS_BRIDGE ]]
}

is_init() {
    [[ "$MERCKU_IS_INIT" -eq 1 ]]
}

is_mesh_2g_enabled() {
    [[ "$MESH_2G_ENABLE" -eq 1 ]]
}

is_normal_state() {
    [[ "$MERCKU_MESH_NODE_STATE" -eq $MERCKU_NODE_STATE_NORMAL ]]
}

is_factory_tested() {
    [[ "$MERCKU_FACTORY_MODE" -eq 0 ]]
}

is_main_5g_enabled() {
    is_uci_value_true "$MERCKU_MAIN_5G_ENABLED"
}

is_keys_lock() {
    local keylock=$(uci get system.child_lock.enabled)

    is_uci_value_true "$keylock"
}

is_network_state() {
    [[ "$MERCKU_STATUS_LED_NERWORK_STATE" -eq 2 ]]
}

is_led_enabled() {
    local led_enabled=$(uci get led_enabled.global.enabled)
    is_uci_value_true "$led_enabled"
}

is_upgrading() {
    [[ "$MERCKU_MESH_NODE_STATE" -eq $MERCKU_NODE_STATE_UPGRADING ]] ||
        [[ "$MERCKU_MESH_NODE_STATE" -eq $MERCKU_NODE_STATE_UPGRADED_FAILED ]] ||
        [[ "$MERCKU_MESH_NODE_STATE" -eq $MERCKU_NODE_STATE_DOWNLOADING_FW ]] ||
        [[ "$MERCKU_MESH_NODE_STATE" -eq $MERCKU_NODE_STATE_DOWNLOAD_FW_FAILED ]] ||
        [[ "$MERCKU_MESH_NODE_STATE" -eq $MERCKU_NODE_STATE_INSTALLING_FW ]] ||
        [[ "$MERCKU_MESH_NODE_STATE" -eq $MERCKU_NODE_STATE_INSTALL_FW_FAILED ]]
}

stop_mercku_services() {
    /etc/init.d/uhttpd stop
    /etc/init.d/merckud stop
    /etc/init.d/mercku_meshd stop
    /etc/init.d/mercku_noded stop
    /etc/init.d/mercku_syncd stop
    /etc/init.d/mercku_mqttd stop
    /etc/init.d/mercku_device_update stop
}

is_uci_value_true() {
    [[ "$1" == "true" ]] || [[ "$1" == "1" ]] || [[ "$1" == "on" ]] || [[ "$1" == "enabled" ]]
}

str_case_cmp() {
    local str1=$(echo $1 | awk '{print toupper($1)}')
    local str2=$(echo $2 | awk '{print toupper($1)}')
    [[ "$str1" == "$str2" ]]
}

str_find() {
    local strf=$(echo "$1" | grep "$2")
    [[ -n "$strf" ]]
}

get_iface_ipaddr() {
    # ifconfig br0 | awk -F "[ :]+" '/inet addr/{print $4}'
    # ifconfig br0 | awk '/inet addr:/{split($2, a, ":"); print a[2]}'
    # ip addr show dev br0 | awk -F'/|[[:blank:]]+' '/inet /{print $3}'
    ip addr show dev $1 | awk '/inet /{split($2, a, "/"); print a[1]}'
}

# default lan ip
MERCKU_MASTER_IP=$(uci get network.lan.default_lan_ip)
MERCKU_SLAVE_IP="169.254.127.1"

is_master && MERCKU_DEFAULT_LAN_IP=$MERCKU_MASTER_IP || MERCKU_DEFAULT_LAN_IP=$MERCKU_SLAVE_IP

# network restart status
NETWORK_LOCK_FILE="/tmp/mercku_network.lock"
is_network_restarting() {
    [[ -e $NETWORK_LOCK_FILE ]]
}

wait_for_network_finish_restart() {
    while true; do
        is_network_restarting && sleep 2 || return 0
    done
}

# wan iface
MERCKU_WAN_IFACE=$(uci get network.wan.ifname)

# clear netfilter connection tracking table
CONNTRACK_FILE="/proc/net/nf_conntrack"
clear_all_conntrack() {
    local all_hnat_entry
    local hant_idx
    [[ -e ${CONNTRACK_FILE} ]] && echo "f" > $CONNTRACK_FILE

    all_hnat_entry=$(awk 'BEGIN{FS="[|=]";ORS=" "} {if($6=="BIND") print $4}' /sys/kernel/debug/hnat/all_entry)
    for hant_idx in $all_hnat_entry; do
        echo "3 ${hant_idx}" > /sys/kernel/debug/hnat/hnat_entry
    done
}

clear_one_conntrack() {
    local src_ip=$1
    local all_hnat_entry
    local hant_idx
    [[ -e ${CONNTRACK_FILE} ]] && echo "$src_ip" > $CONNTRACK_FILE

    # clear hnat entries
    all_hnat_entry=$(awk 'BEGIN{FS="[|=]";ORS=" "} $0~src_ip {if($6=="BIND") print $4}' src_ip=${src_ip} /sys/kernel/debug/hnat/all_entry)
    for hant_idx in $all_hnat_entry; do
        echo "3 ${hant_idx}" > /sys/kernel/debug/hnat/hnat_entry
    done
}

clear_nf_conntrack() {
    local tmp_file=$(mktemp -u /tmp/contrack_file.XXXXXX)
    local wan_ip=$(get_iface_ipaddr $MERCKU_WAN_IFACE)

    cut -d '=' -f2 $CONNTRACK_FILE | cut -d ' ' -f1 | sort | uniq > $tmp_file
    while read tmp_ip; do
        [[ "$tmp_ip" == "$wan_ip" || "$tmp_ip" == "0.0.0.0" ]] && continue
        clear_one_conntrack $tmp_ip
    done < $tmp_file
    rm -f $tmp_file
}

# wan & lan switch port id
MERCKU_WAN_PORT_ID=4
MERCKU_LAN_PORT2_ID=3
MERCKU_LAN_PORT1_ID=2

# mercku_factory_debug <$1 - debug msg>
mercku_factory_debug() {
    [[ $MERCKU_FACTORY_MODE -eq 0 ]] && return

    echo "$1" >> $MERCKU_FACTORY_TEST_FILE
}

# mercku_debug <$1 - debug tag> <$2 - debug msg>
mercku_debug() {
    logger -s -p "user.debug" -t "$1" "$2"
}

# In slave mode, guest wifi's ifname is automatically generated by the wsplcd program. We need to find it out by iwconfig
MERCKU_GUEST_5G_IFNAME=""
MERCKU_GUEST_2G_IFNAME=""
TMP_GUEST_IFNAME=""

__find_if_minor_id() {
    local ssid=$1
    local major_id=$2
    local minor_id=1

    while [[ $minor_id -le 4 ]]; do
        iwconfig "ath${major_id}${minor_id}" | grep "$ssid" > /dev/null 2>&1
        [[ $? -eq 0 ]] && echo $minor_id && return 0
        let minor_id+=1
    done
    return 1
}

__get_ifname() {
    # wifi0:5g wifi1:2.4g
    local guest_device=$1
    # 32: guest
    local map_type=$2

    # ath01: major id is 0,minor id is 1
    # 0 : 5g 1: 2.4g
    local if_major_id=$3
    # 1-4
    local if_minor_id

    # 0-7 is valid
    local iface_num=0

    local tmp_ssid
    local tmp_device
    local tmp_type

    while [[ $iface_num -lt 8 ]]; do
        # skipping sections that has option 'ifname'
        uci get wireless.@wifi-iface[$iface_num] > /dev/null 2>&1 || return 1
        uci get wireless.@wifi-iface[$iface_num].ifname > /dev/null 2>&1 && let iface_num+=1 && continue

        # to find out guest device
        tmp_device=$(uci get wireless.@wifi-iface[$iface_num].device)
        tmp_type=$(uci get wireless.@wifi-iface[$iface_num].MapBSSType)
        [[ "$guest_device" != "$tmp_device" || "$map_type" != "$tmp_type" ]] && let iface_num+=1 && continue

        # get ssid
        tmp_ssid=$(uci get wireless.@wifi-iface[$iface_num].ssid)
        [[ -z "$tmp_ssid" ]] && let iface_num+=1 && continue

        # get ifname by command 'iwconfig'
        if_minor_id=$(__find_if_minor_id "$ssid" "$if_major_id")
        [[ -z "$if_minor_id" ]] && let iface_num+=1 && continue
        TMP_GUEST_IFNAME="ath${if_major_id}${if_minor_id}"
        return 0
    done
    return 1
}

guest_5g_ifname() {
    TMP_GUEST_IFNAME=""
    is_master && MERCKU_GUEST_5G_IFNAME=$(uci get wireless.guest_5g.ifname) && return 0
    __get_ifname wifi0 32 0 && MERCKU_GUEST_5G_IFNAME=$TMP_GUEST_IFNAME || return 1

}

guest_2g_ifname() {
    TMP_GUEST_IFNAME=""
    is_master && MERCKU_GUEST_2G_IFNAME=$(uci get wireless.guest_2g.ifname) && return 0
    __get_ifname wifi1 32 1 && MERCKU_GUEST_2G_IFNAME=$TMP_GUEST_IFNAME || return 1
}

MERCKU_BOOT_DONE_FILE=/var/run/mercku_boot_done

mercku_set_boot_done() {
    touch $MERCKU_BOOT_DONE_FILE
}

mercku_is_boot_done() {
    [[ -e $MERCKU_BOOT_DONE_FILE ]]
}

mercku_lock_network_restart() {
    [[ -f "$MERCKU_NETWORK_LOCK_FILE" ]] && echo "network is restarting" > /dev/console && return 1
    touch $MERCKU_NETWORK_LOCK_FILE
    return 0
}

mercku_unlock_network_restart() {
    [[ -f "$MERCKU_NETWORK_LOCK_FILE" ]] && rm -f $MERCKU_NETWORK_LOCK_FILE
}

is_network_restarting() {
    [[ -f "$MERCKU_NETWORK_LOCK_FILE" ]]
}

# batch_datconf(string dst_file, string batch_lines)
batch_datconf() {
    local dst_file=$1
    local batch_lines=$2
    local tmp_dst_2g="/tmp/mercku/wireless/mt7915.dbdc.b0.dat"
    local tmp_dst_5g="/tmp/mercku/wireless/mt7915.dbdc.b1.dat"
    echo -e "${batch_lines}" | datconf -f ${dst_file} batch
    # if [ "/etc/wireless/mediatek/mt7915.dbdc.b0.dat" == $1 ]; then
    #     echo -e "${batch_lines}" | datconf -f ${tmp_dst_2g} batch
    #     flock "${dst_file}" cp "${tmp_dst_2g}" "${dst_file}"
    # elif [ "/etc/wireless/mediatek/mt7915.dbdc.b1.dat" == $1 ]; then
    #     echo -e "${batch_lines}" | datconf -f ${tmp_dst_5g} batch
    #     flock "${dst_file}" cp "${tmp_dst_5g}" "${dst_file}"
    # else
    #     return
    # fi
}
